不適切なワードや画像を手軽に検出できるSaaS WebPurifyをつかってみた
みなさん大根はお好きですか?
今回は、チャットや掲示板などでよく見る
- 攻撃的な言葉を送信したら非表示になる
-
卑猥な画像をアップロードしても表示されない
といった、あの機能を手軽に実装できないか調べてみました。
いくつか候補があったのですが、Free Trialで利用できるWebPurifyというサービスを試してみました。
WebPurifyの特徴
WebPurifyは主に以下の3つの機能に分類されます。
それぞれ文字、画像、動画に不適切な情報が含まれていないか検知することが可能です。
- Profanity Filter
- Photo Moderation
- Video Moderation
それぞれAPIが用意されており、HTTP経由で判定を行うことができます。
英語では、NGワードフィルタのことをProfanity(冒涜的、口汚い罵り) Filter
、画像の検出をImage Moderation
なんて読んだりするそうです。
Profanity Filter
- 15言語対応した辞書を持っている
- カスタムでBlock & Allow listsにワードを登録できる
Photo Moderation
AI
では、AIによる自動判定ができる(あくまでWebPurify側が用意したモデル)Live
では、訓練されたライブチームによる人力判定ができるAI
とLive
を組み合わせて、自動判定して怪しそうな画像から人力でフィルタするということもできる- 文字認識(OCR)もできて、前述の
Profanity Filter
と組み合わせて不適切なワードも検出できる
Video Moderation
- こちらも
AI
とLive
の2つがある
Profanity Filterをつかってみる
Profanity Filter
では主に
- 不適切なワードの検出
- 不適切なワードの置換
- カスタムBlock & Allow listsへのワード登録
という3つの機能があります。
これらをAPI Docsを参考に試していきます。
今回テストデータとして、
「NoSQLを思考停止で使うと死ねる」
という文章を判定してみます。
はたしてこの文章は不適切なのでしょうか?
不適切なワードが含まれているかチェック
不適切なワードが含まれていれば1が返ります。
リクエストはこんな感じの形式です。すべてクエリパラメータで表現していますね。
http://api1.webpurify.com/services/rest/?api_key=[your-api-key]&method=webpurify.live.check&text=NoSQL%E3%82%92%E6%80%9D%E8%80%83%E5%81%9C%E6%AD%A2%E3%81%A7%E4%BD%BF%E3%81%86%E3%81%A8%E6%AD%BB%E3%81%AD%E3%82%8B&lang=jp&format=json
- Request Parameters
- Text:
NoSQLを思考停止で使うと死ねる
- Language:
Japanese
- Method:
webpurify.live.check
- Text:
- Response
{ "rsp": { "@attributes": { "stat": "ok" }, "method": "webpurify.live.check", "lang": "jp", "format": "rest", "found": "1", "api_key": "xxxxx" } }
"found": "1"
となり、検出されたのがわかります。
ちなみにシネ
、4ね
、タヒね
、タヒね
あたりを試してみましたが、検出されませんでした。
不適切なワードを任意の文字列に置換
不適切なワードを任意の文字に置換します。
- Request Parameters
- Text:
NoSQLを思考停止で使うと死ねる
- Replace Symbol:
*
- Language:
Japanese
- Method:
webpurify.live.replace
- Text:
- Response
{ "rsp": { "@attributes": { "stat": "ok" }, "method": "webpurify.live.replace", "lang": "jp", "format": "rest", "found": "1", "text": "*****************************************", "api_key": "xxxxx" } }
想定だと一部が置換される予定でしたが、テキスト全体が置換されてしまいましたね。。。
英語のように単語の間にスペース区切りがある場合はうまく動作したのですが、日本語だと難しのかもしれません。
Allow Listへの追加
死ねる
は不適切なワードではないと判断し、Allow Listに追加します。
- Request Parameters
- Word:
死ねる
- Language:
Japanese
- Deep Search:
1
※部分文字列一致の場合でもフィルタする - Method:
webpurify.live.addtoallowlist
- Word:
Allow Listに追加した後、NoSQLを思考停止で使うと死ねる
で再度チェックしてみます。
- Request Parameters
- Text:
NoSQLを思考停止で使うと死ねる
- Language:
Japanese
- Method:
webpurify.live.check
- Text:
- Response
{ "rsp": { "@attributes": { "stat": "ok" }, "method": "webpurify.live.check", "lang": "jp", "format": "rest", "found": "0", "api_key": "xxxxx" } }
"found": "0"
となり検出されなくなりましたね。
Block Listへの追加
タヒね
を不適切なワードと判断し、BlockListへ追加します。
- Request Parameters
- Word:
タヒね
- Language:
Japanese
- Deep Search:
1
- Method:
webpurify.live.addtoblocklist
- Word:
Allow Listに追加した後、今度はNoSQLを思考停止で使うとタヒねる
という文章でチェックしてみます。
- Request Parameters
- Text:
NoSQLを思考停止で使うとタヒねる
- Language:
Japanese
- Method:
webpurify.live.check
- Text:
- Response
{ "rsp": { "@attributes": { "stat": "ok" }, "method": "webpurify.live.check", "lang": "jp", "format": "rest", "found": "1", "api_key": "xxxxx" } }
"found": "1"
となっているので、検出できました。
置換も試してみます。
- Request Parameters
- Text:
NoSQLを思考停止で使うとタヒねる
- Replace Symbol:
*
- Language:
Japanese
- Method:
webpurify.live.replace
- Text:
- Response
{ "rsp": { "@attributes": { "stat": "ok" }, "method": "webpurify.live.replace", "lang": "jp", "format": "rest", "found": "2", "text": "NoSQL\u3092\u601d\u8003\u505c\u6b62\u3067\u4f7f\u3046\u3068*********\u308b", "api_key": "xxxxx" } }
今度は一部だけ置換されましたね。
ここは謎ですが、カスタム登録したワードだと挙動が変わるのかもしれません。
Photo Moderationをやってみる
Photo ModerationではLive
とAI
の2つの機能があります。
AI
では、最新の機械学習技術を用いて、ヌード、武器、アルコール、攻撃的なシンボル、ジェスチャー、有名人、テキストなどを検出してくれます。
一方、Live
ではライブチームが人力で判断してくれます
またHybrid Approach
を使うことで、AI
で一定の閾値を超えた画像を、さらにLive
で人力で判定するというアプローチもできます。
これらをAPIドキュメントを参考にためしていきます。
今回テストデータとしてこちらのフリー素材を利用させて頂きました。
念のため断っておきますが、ただの大根ですよ。
AIでの自動判定
- Request Parameters
- Image URL:
https://i1.wp.com/sozai-dc.com/wp-content/uploads/dcimage/food/hiwaidaikon.png
- Categories:
nudity,wad,offensive,celebrities,text,faces,ocr,scam
- Method:
webpurify.aim.imgcheck
- Image URL:
- Response
{ "rsp": { "@attributes": { "stat": "ok" }, "method": "webpurify.aim.imgcheck", "format": "rest", "categories": "8", "nudity": "88", "nuditypartial": "1", "nuditysafe": "11", "weapon": "1", "alcohol": "1", "drugs": "1", "offensive": "1", "artificialtext": "17", "naturaltext": "87", "scam": "1", "ocr_text": "", "ocr_profanity": "0", "api_key": "xxxxx" } }
おや?おかしいですね。nudity(裸の状態)
の値が88を超えましたね。
Hybrid Approachで人力判定も追加
先ほどの大根さんの画像がnudity(裸の状態)
と判定されてしまったので、ライブチームへ確認してもらおうと思います。
閾値を設定して、閾値を超えたらLive
で判定してもらうようにします。
- Request Parameters
- Image URL:
https://i1.wp.com/sozai-dc.com/wp-content/uploads/dcimage/food/hiwaidaikon.png
- Categories:
nudity
- Threshold Nudity Greater Than:
80
- Method:
webpurify.hybrid.imgcheck
- Image URL:
- Response
{ "rsp": { "@attributes": { "stat": "ok" }, "method": "webpurify.hybrid.imgcheck", "format": "rest", "categories": "1", "nudity": "88", "nuditypartial": "1", "nuditysafe": "11", "imgid": "e3a191e3197c7b5f0d0e0980f532ec8b", "status": "pending", "api_key": "xxxxx" } }
imgid
が返ってきました。
ライブチームからの結果の取得方法はいくつかあるようですが、今回はAPIで結果を取得します。
- Request Parameters
- Image ID:
e3a191e3197c7b5f0d0e0980f532ec8b
- Method:
webpurify.live.imgstatus
- Image ID:
- Response
{ "rsp": { "@attributes": { "stat": "ok" }, "method": "webpurify.live.imgstatus", "format": "rest", "imgid": "e3a191e3197c7b5f0d0e0980f532ec8b", "sdate": "2021-08-03 00:46:47", "mdate": "2021-08-03 00:47:15", "status": "approved", "api_key": "xxxxx" } }
statusがapproved
となっています。
どうやら大根と判断されたのでしょうか?
そりゃそうですよね。どう見ても大根ですよね?
まとめ
いかがだったでしょうか。
ワードのフィルターに関しては、辞書さえあればパターンマッチで自前実装できそうなので、SaaS使いつつ裏で辞書登録したりするのもアリかなと思いました。
画像のフィルターに関しては、もし自前実装するのであれば、Amazon Rekognitionに同等の機能があるのでこちらを使うのもアリかもしれません。
いずれにせよAPIで手軽に利用できるのはとても便利ですね!